<script setup lang="ts">
import AppTable from "@/components/app/AppTable.vue";
import whitelistDialog from "@/views/system/auth/whitelistDialog.vue"
import {Close, Right, Document} from "@element-plus/icons-vue";
import {ref} from "vue";
import {alertError, alertSuccess, confirm} from "@/utils/alert.ts";
import {addRolePermission, addUrlToWhitelist, removeRolePermission} from "@/api/system";

defineOptions({
  // eslint-disable-next-line vue/multi-word-component-names
  name: "Auth"
})

const tableRef = ref()
const showWhitelistDialog = ref(false)
const selectRoles = ref<IRole[]>([])
const showRoleListDialog = ref<boolean>(false)
const showAddToWhitelistDialog = ref<boolean>(false)
const isAddOrRemove = ref<boolean>(true)
const whitelist = ref<IWhitelist[]>([])

interface IRole {
  id: string
  label: string
  value: string
  permCount: number
}

interface IWhitelist {
  id: string;
  httpMethod: string;
  httpUrl: string;
  allowAnonymous: boolean;
}

const selectList = ref<{
  id: string
  httpMethod: string
  httpUrl: string
  className: string
  method: string
  inWhitelist: string
  allowAnonymous: string
}[]>([])


const rightSelectListBox = ref<{
  id: string
  httpMethod: string
  httpUrl: string
  className: string
  method: string
  inWhitelist: string
  allowAnonymous: string
}[]>([])

const append = () => {
  //去重push
  selectList.value.forEach(item => {
    if (!rightSelectListBox.value.some(item2 => item2.id === item.id)) {
      rightSelectListBox.value.unshift(item)
    }
  })
  selectList.value = []
  tableRef.value.handleClearSelection()
}

const clear = () => {
  rightSelectListBox.value = []
}

const submit = (addPermissions: boolean) => {
  let msg = ""
  if (addPermissions) {
    msg = `确定要添加${rightSelectListBox.value.length}个权限给[${selectRoles.value.map(item => item?.label).join(',')}]吗`
  } else {
    msg = `确定要解除[${selectRoles.value.map(item => item?.label).join(',')}]的${rightSelectListBox.value.length}个权限吗`
  }
  confirm(msg, () => {
    const data = {
      roleIds: selectRoles.value.map(item => item.id),
      urlIds: rightSelectListBox.value.map(item => item.id),
    }
    if (addPermissions) {
      addRolePermission(data).then(() => {
        alertSuccess("添加权限成功！")
        tableRef.value.queryData()
      })
    } else {
      removeRolePermission(data).then(() => {
        alertSuccess("解除权限成功！")
        tableRef.value.queryData()
      })
    }
  })
}

const remove = (index: number) => {
  rightSelectListBox.value.splice(index, 1)
}

const openRoleListDialog = (flag: boolean) => {
  isAddOrRemove.value = flag;
  selectRoles.value = [];
  showRoleListDialog.value = true;
}

const afterSelectRole = () => {
  if (selectRoles.value.length === 0) {
    alertError("请您需要操作的角色！")
    return
  }
  showRoleListDialog.value = false;
  submit(isAddOrRemove.value)
}


const addToWhitelist = () => {
  whitelist.value = rightSelectListBox.value.map(item => {
    return {
      id: item.id,
      httpMethod: item.httpMethod,
      httpUrl: item.httpUrl,
      allowAnonymous: true
    }
  })
  showAddToWhitelistDialog.value = true;

}

const submitWhitelist = () => {
  confirm(`确定要将${rightSelectListBox.value.length}个权限移入访问白名单吗`, () => {
    addUrlToWhitelist(whitelist.value.map(item => {
      return {
        urlId: item.id,
        allowAnonymous: item.allowAnonymous ? "0" : "1"
      }
    })).then(() => {
      alertSuccess("已移入访问白名单！")
      tableRef.value.queryData()
      closeAddToWhitelistDialog()
    })
  })
}

const closeAddToWhitelistDialog = () => {
  showAddToWhitelistDialog.value = false;
  whitelist.value = []
}

</script>

<template>
  <div class="auth-container">
    <el-row class="main-content">
      <el-col class="table-col">
        <div class="table-wrapper">
          <AppTable
            ref="tableRef"
            :search-info="[{
      label: '查询参数',
      key: 'keyword',
      value: ''
    }]"
            :margin-able="false"
            :btn-show="{add: false,edit: false,delete: false, export:false,import:false}"
            :table-style="{
                height: '58vh'
              }"
            :pageable="false"
            api-method="get"
            api-path="/api/sys/url/queryWithRolesList"
            @multiple-selection="data => {selectList = data}">
            <template v-slot:actionBar>
              <div style="display: flex;justify-content: space-between">
                <div>
                  <el-button
                    @click="()=>{showWhitelistDialog = true}"
                    :icon="Document" type="primary">白名单管理
                  </el-button>
                </div>
                <div style="text-align: right">
                  <el-button @click="append" style="margin-left: auto"
                             :disabled="selectList.length === 0"
                             :icon="Right" type="primary">添加
                  </el-button>
                </div>
              </div>
            </template>
            <template v-slot:tableColumn>
              <el-table-column prop="httpMethod" label="请求方法" align="center" width="90">
                <template #default="scope">
                  <el-tag :type="scope.row.httpMethod === 'GET' ? 'primary' :
                               scope.row.httpMethod === 'POST' ? 'success' :
                               scope.row.httpMethod === 'PUT' ? 'warning' :
                               scope.row.httpMethod === 'DELETE' ? 'danger' : ''">
                    {{ scope.row.httpMethod }}
                  </el-tag>
                </template>
              </el-table-column>
              <el-table-column prop="httpUrl" label="请求地址" align="left"/>
              <el-table-column prop="inWhitelist" label="白名单内" align="center" width="90">
                <template #default="scope">
                  <el-tag v-if="scope.row.inWhitelist === 'y'" type="success" size="small">是
                  </el-tag>
                  <el-tag v-if="scope.row.inWhitelist === 'n'" type="danger" size="small">否
                  </el-tag>
                </template>
              </el-table-column>
              <el-table-column prop="allowAnonymous" label="匿名访问" align="center" width="90">
                <template #default="scope">
                  <el-tag v-if="scope.row.allowAnonymous === 'y'" type="success" size="small">是
                  </el-tag>
                  <el-tag v-if="scope.row.allowAnonymous === 'n'" type="danger" size="small">否
                  </el-tag>
                </template>
              </el-table-column>
              <el-table-column label="允许访问的角色" align="left" width="230">
                <template v-slot="scope">
                  <el-tag :type="item.id === '1' ? 'danger' :
                               item.id === '2' ? 'success' :
                               item.id === '3' ? 'warning' :
                               item.id === '4' ? 'info' : 'primary'"
                          v-for="(item,index) in scope.row.sysRoles" :key="index"
                          size="small"
                          style="margin: 0 5px 5px 0">
                    {{ item.roleName }}
                  </el-tag>
                </template>
              </el-table-column>
            </template>
          </AppTable>
        </div>
      </el-col>
      <el-col class="selection-col">
        <div class="selection-header">
          <el-row>
            <el-col :span="8">
              <h3>已选择接口 (<span style="color: #008500;">{{
                  rightSelectListBox.length
                }}</span>)</h3>
            </el-col>
            <el-col :span="16" style="text-align: right">
              <el-button :disabled="rightSelectListBox.length===0" type="primary" size="small"
                         @click="addToWhitelist()">
                移 入 白 名 单
              </el-button>
              <el-button :disabled="rightSelectListBox.length===0" type="danger" size="small"
                         @click="openRoleListDialog(false)">
                解 权
              </el-button>
              <el-button :disabled="rightSelectListBox.length===0" type="success" size="small"
                         @click="openRoleListDialog(true)">
                授 权
              </el-button>

              <el-button :disabled="rightSelectListBox.length===0" type="info" size="small"
                         @click="clear">
                清 空
              </el-button>
            </el-col>
          </el-row>
        </div>
        <div class="selection-scroll">
          <div class="selection-content">
            <el-card
              class="box-card-selected"
              v-for="(item,index) in rightSelectListBox"
              :key="item?.id"
              shadow="hover">
              <template #header>
                <div class="card-header">
                  <span>{{ rightSelectListBox.length - index }}</span>
                  <el-tag :type="item.httpMethod === 'GET' ? 'primary' :
                               item.httpMethod === 'POST' ? 'success' :
                               item.httpMethod === 'PUT' ? 'warning' :
                               item.httpMethod === 'DELETE' ? 'danger' : ''">
                    {{ item.httpMethod }}
                  </el-tag>
                  <el-button size="small" style="margin-left: auto;"
                             plain :icon="Close " type="danger" @click="remove(index)">
                  </el-button>
                </div>
              </template>
              <div class="card-body">
                <p class="info-item"><span
                  class="info-item-label">接口地址：</span>{{ item.httpUrl }}</p>
                <p class="info-item"><span
                  class="info-item-label">类名方法：</span>{{ item.className }} # {{
                    item.method
                  }}</p>

                <p class="info-item"><span
                  class="info-item-label">白名单内：</span>{{ item.inWhitelist }}</p>
                <p class="info-item"><span
                  class="info-item-label">匿名访问：</span>{{ item.allowAnonymous }}</p>
                <p class="info-item">
                  <span class="info-item-label">原允许访问角色：</span>
                  <span v-for="(role,index) in item.sysRoles" :key="index"
                        style="margin: 0 5px 5px 0">
                        {{ role.roleName }}
                      </span>
                </p>
              </div>
              <div class="card-footer">
              </div>
            </el-card>

            <div v-if="rightSelectListBox.length === 0" class="empty-selection">
              <el-empty description="暂未选择任何接口" :image-size="80"/>
            </div>
          </div>
        </div>
      </el-col>
    </el-row>


    <el-dialog v-model="showAddToWhitelistDialog"
               align-center
               :destroy-on-close="true"
               :before-close="closeAddToWhitelistDialog"
               title="添加白名单" width="800px" :close-on-click-modal="false">
      <el-table
        :data="whitelist"
        style="width: 100%;height: 70vh">
        <el-table-column
          label="请求方法"
          width="80"
          align="center">
          <template #default="scope">
            {{ scope.row.httpMethod }}
          </template>
        </el-table-column>
        <el-table-column
          label="请求URL"
          align="left">
          <template #default="scope">
            {{ scope.row.httpUrl }}
          </template>
        </el-table-column>
        <el-table-column
          label="未登录访问"
          align="center">
          <template #default="scope">
            <el-switch v-model="scope.row.allowAnonymous"
                       active-text="允许"
                       inactive-text="禁止"
                       active-color="#13ce66"
                       inactive-color="#ff4949"
            >
            </el-switch>
          </template>
        </el-table-column>
      </el-table>

      <template #footer>
        <el-button @click="closeAddToWhitelistDialog">取消</el-button>
        <el-button type="primary" @click="submitWhitelist">保存</el-button>
      </template>
    </el-dialog>


    <el-dialog v-model="showRoleListDialog"
               align-center
               :destroy-on-close="true"
               title="选择操作角色" width="800px" :close-on-click-modal="false">
      <AppTable
        title="角色管理"
        :search-info="[
      {
      label: '角色名称',
      key: 'roleName',
      value: ''
    }]"
        :btn-show="{
      add: false,
      edit: false,
      delete: false,
      export:false,
      import:false
    }"
        :pageable="false"
        api-method="get"
        api-path="/api/sys/role/query"
        @multiple-selection="data => {selectRoles =  data}">
        <template v-slot:actionBar>
        </template>
        <template v-slot:tableColumn>
          <el-table-column label="角色名称" align="left">
            <template v-slot="scope">
              <el-tag type="warning">{{ scope.row.label }}</el-tag>
            </template>
          </el-table-column>
          <el-table-column label="权限字符" align="left">
            <template v-slot="scope">
              <el-tag type="success">{{ scope.row.value }}</el-tag>
            </template>
          </el-table-column>
          <el-table-column label="接口权限个数" align="center">
            <template v-slot="scope">
              <div v-if="scope.row.value==='admin'" style="color: red">
                全系统权限
              </div>
              <div v-else>
                {{ scope.row.permCount }}
              </div>
            </template>
          </el-table-column>
        </template>
      </AppTable>
      <template #footer>
        <el-button :disabled="selectRoles.length === 0" type="primary" @click="afterSelectRole">
          确定
        </el-button>
      </template>
    </el-dialog>
    <whitelistDialog :show-dialog="showWhitelistDialog"
                     :before-close="()=>{showWhitelistDialog = false}"/>
  </div>
</template>

<style scoped>

.auth-container {
  width: 100%;
  height: calc(100vh - 140px);
}

.main-content {
  height: 100%;
  display: flex;
}

.table-col {
  flex: 3;
}

.selection-col {
  height: 100%;
  flex: 2;
  padding: 18px;
}

.selection-header {
  background: white;
  padding: 12px 15px;
  border-radius: 6px 6px 0 0;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  border-bottom: 1px solid #e4e7ed;
}

.selection-header h3 {
  margin: 0;
  color: #303133;
  font-size: 16px;
}

.selection-scroll {
  height: calc(100% - 55px);
  background: white;
  border-radius: 0 0 6px 6px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  overflow: auto;
}

.selection-content {
  padding: 15px;
}

.box-card-selected {
  margin-bottom: 15px;
  border: 1px solid #ebeef5;
  border-radius: 6px;
  transition: all 0.3s;
}

.box-card-selected:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.15);
  border-color: #c6e2ff;
}

.card-header {
  display: flex;
  align-items: center;
  gap: 10px;
}


.card-body {
  padding: 10px 0 0;
}

.info-item {
  margin: 8px 0;
  font-size: 12px;
  word-break: break-word;
  text-overflow: ellipsis;
  gap: 5px;
  font-weight: 400;
  white-space: pre-wrap;
  padding-bottom: 10px;
  border-bottom: 1px solid #e4e7ed;
}

.info-item .info-item-label {
  font-weight: 500;
  color: #0e9725;
  font-size: 12px;
}

.empty-selection {
  text-align: center;
  padding: 30px 0;
}

:deep(.el-table__row:hover) {
  background-color: #f5f7fa !important;
}
</style>
